﻿using System;
using System.IO;
using System.IO.Packaging;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using Duellum.Core;

namespace Duellum.Wpf2d.Plugin
{
	//internal class ImageCache : ObjectPool<Uri,BitmapSource>
	//{
	//    protected override BitmapSource CreateItem(Uri key)
	//    {
	//        return new BitmapImage(key);
	//    }
	//}

	internal class ImagePackageCache : ObjectPool<string,BitmapSource>, IDisposable
	{
		Package package;
		
		public ImagePackageCache(Package pkg)
		{
			this.package = pkg;
		}

		private static Exception CannotLoadResource(Uri uriResource, Exception innerException)
		{
			return new ApplicationException(string.Format("Cannot load resource '{0}'", uriResource), innerException);
		}
		
		protected override BitmapSource CreateItem(string key)
		{
			var uri = PackUriHelper.CreatePartUri(new Uri(key, UriKind.Relative));
			PackagePart part;
			try {
				part = package.GetPart(uri);
			} catch (InvalidOperationException ex) {
				throw CannotLoadResource(uri, ex);
			}
			
			using (var stream = part.GetStream(FileMode.Open)) {
				var bmp = new BitmapImage();
				bmp.BeginInit();
				bmp.CacheOption = BitmapCacheOption.OnLoad;
				bmp.StreamSource = stream;
				bmp.EndInit();
				bmp.Freeze();
				return bmp;
			}
		}

		public void Dispose()
		{
			((IDisposable)package).Dispose();
		}
	}
	
	internal class PopupControlServiceInterop
	{
		static public PopupControlServiceInterop Current = new PopupControlServiceInterop();
		
		Action<IInputElement,Point> onMouseMoveFunc;
		
		private PopupControlServiceInterop()
		{
			//using System.Windows.Controls.PopupControlService
			var a = Assembly.GetAssembly(typeof(ToolTipService));
			var t = a.GetType("System.Windows.Controls.PopupControlService");
			
			//var current = PopupControlService.Current
			var getCurrent = t.GetProperty("Current", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy);
			var current = getCurrent.GetValue(null, null);
			
			//current.OnMouseMove(IInputElement directlyOver, Point pt)
			var m = t.GetMethod("OnMouseMove", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
			var f = (Action<IInputElement,Point>)Delegate.CreateDelegate(typeof(Action<IInputElement,Point>), current, m);
			
			onMouseMoveFunc = f;
			//m.Invoke(current, new object[]{null, null});
			//m.Invoke(current, new object[]{this, null});
		}
		
		public void OnMouseMove(IInputElement directlyOver, Point pt)
		{
			onMouseMoveFunc(directlyOver, pt);
		}
	}
}
